﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;

/*
    Copyright (C) 2010 Officebroker.com LTD.
    Neil Cadman, Alex Welding, Andrew Coombs, Jan Rygielski
    Sir Robert Peel Mill, Mill Lane, Staffordshire, Fazely, B78 3QD, England

    This file is part of OBiCMSFramework.

    OBiCMSFramework is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OBiCMSFramework is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License (GNU AGPL)
    along with OBiCMSFramework.  If not, see <http://www.gnu.org/licenses/>.
*/

namespace OBiCMSFramework
{
    // Public Classes
    [Serializable()]
    public abstract class WidgetBase : BasePage.BasePageJob.BasePageJobType
    {
        // Private Variables
        private Boolean _runThreadAgain = true;
        private DateTime _dateChanged;
        private Hashtable _postBackData = new Hashtable();
        private Int32 _minRefreshTime = 60000;
        private Int32 _maxRefreshTime = 120000;
        private List<WidgetBase> _innerWidgets = new List<WidgetBase>();
        private String _id = "";

        // Public Properties
        public DateTime DateChanged
        {
            get { return _dateChanged; }
            set { _dateChanged = value; }
        }
        public Int32 MinRefreshTime
        {
            get { return _minRefreshTime; }
            set { _minRefreshTime = value; }
        }
        public Int32 MaxRefreshTime
        {
            get { return _maxRefreshTime; }
            set { _maxRefreshTime = value; }
        }
        public List<WidgetBase> InnerWidgets
        {
            get { return _innerWidgets; }
        }
        public String ID
        {
            get { return _id; }
            set { _id = value; }
        }

        // Private Delegates
        private delegate void loadWidgetDelegate(Int32 startStall);

        // Public Constructors
        public WidgetBase(String id)
        {
            _id = id;
        }

        // Public methods
        public abstract List<String> DefaultSettings();
        public abstract StringBuilder PostBack(BasePage.ContextManager context, BasePage.PageSettings pageSettings, String widgetSettings, Stopwatch timer, Boolean useDiagnostics);
        public abstract StringBuilder GenerateWidget(BasePage.ContextManager context, BasePage.PageSettings pageSettings, String widgetSettings, Stopwatch timer, Boolean useDiagnostics);

        /// <summary>
        /// This will add a DebugItem to be used if a Widget crashes.
        /// </summary>
        /// <param name="name">The name you want the value to relate to</param>
        /// <param name="value">The value of what you want to debug</param>
        public void AddDebugItem(String name, String value)
        {
            ((Dictionary<String, KeyValuePair<String, String>>)System.Web.HttpContext.Current.Session["OBiCMSDebugItems"])
                .Add(this.GetType().Name, new KeyValuePair<String, String>(name, value));
        }

        // Internal Methods
        internal override StringBuilder GeneratePage(BasePage.ContextManager context, BasePage.PageSettings pageSettings, String widgetSettings, Stopwatch timer, Boolean useDiagnostics)
        {
            context.SetSession("OBiCMSDebugItems", new Dictionary<String, KeyValuePair<String, String>>());

            try
            {
                if (pageSettings.PostBackGuid != "" && _postBackData.Contains(pageSettings.PostBackGuid))
                {
                    StringBuilder postbackBody = new StringBuilder((String)_postBackData[pageSettings.PostBackGuid]);

                    _postBackData.Remove(pageSettings.PostBackGuid);

                    return postbackBody;
                }

                return GenerateWidget(context, pageSettings, widgetSettings, timer, useDiagnostics);
            }
            catch (Exception e)
            {
                Dictionary<String, String> tempDebugItems = new Dictionary<String, String>();

                foreach (KeyValuePair<String, KeyValuePair<String, String>> debugItems in (Dictionary<String, KeyValuePair<String, String>>)context.GetSession("OBiCMSDebugItems"))
                    tempDebugItems.Add(debugItems.Key, debugItems.Value.Key + " : " + debugItems.Value.Value);

                throw new OBiHTTPHandler.CMSException("Could not generate Widget - ID : " + e.Message, e, tempDebugItems);
            }
        }
        internal void BeginAutoLoad()
        {
            _runThreadAgain = true;
            AutoLoad();
        }
        internal void StopAutoLoad()
        {
            _runThreadAgain = false;
        }
        internal void InitializeWidget()
        {
            _runThreadAgain = false;
            LoadWidgetBase(0);
            _runThreadAgain = true;
            AutoLoad();
        }

        internal void AutoLoad()
        {
            loadWidgetDelegate autoLoad = new loadWidgetDelegate(LoadWidgetBase);
            autoLoad.BeginInvoke(StaticObjects.RandomFactory.Create().Next(_minRefreshTime, _maxRefreshTime), new AsyncCallback(AutoLoadEnd), null);
        }
        internal void AutoLoadEnd(IAsyncResult result)
        {
        }
        internal void LoadWidgetBase(Int32 startStall)
        {
            try
            {
                if (startStall != 0)
                    Thread.Sleep(startStall);

                LoadWidget();
            }
            catch (Exception e)
            {
                OBiHTTPHandler.CMSException Error = new OBiHTTPHandler.CMSException("Could not load Widget - ID : " + this.ID, e, null);
                StaticObjects.AppendErrorLog(Error);
                throw Error;
            }

            // Automaticly run again?
            if (_runThreadAgain)
            {
                AutoLoad();
            }

        }
        internal void AddPostBackID(String id, String body)
        {
            _postBackData.Add(id, body);
        }

        // Protected Methods
        protected abstract void LoadWidget();
    }

    // Internal Classes
    internal class defaultWidget : WidgetBase
    {
        // Private Variables
        private String _message = "";

        // Public Properties
        public String Message
        {
            get { return _message; }
            set { _message = value; }
        }

        // Public Constructors
        public defaultWidget(String id)
            : base(id)
        {
            MinRefreshTime = Int32.MaxValue - 1;
            MaxRefreshTime = Int32.MaxValue;
        }

        // Protected Methods
        protected override void LoadWidget()
        {
            ;
        }

        // Public Methods
        public override List<String> DefaultSettings()
        {
            return new List<String>();
        }
        public override StringBuilder PostBack(BasePage.ContextManager context, BasePage.PageSettings pageSettings, String widgetSettings, Stopwatch timer, Boolean useDiagnostics)
        {
            return new StringBuilder("");
        }
        public override StringBuilder GenerateWidget(BasePage.ContextManager context, BasePage.PageSettings pageSettings, String widgetSettings, Stopwatch timer, Boolean useDiagnostics)
        {
            return new StringBuilder(_message);
        }
    }
}
